<!--
高德定位组件
-->

<template>
  <div class="if-amap">
    <!-- input组件 $listeners 用于触发blur校验, 如果需要支持change触发校验, @change需要在组件外进行实现 -->
    <el-input
      class="amap-address-text"
      v-model="locationInfo.name"
      @input="locationNameChange"
      :disabled="disabled"
    />
    <!-- 高德定位组件 -->
    <a-map
      ref='amap'
      :style="mapWarpStyle"
      :showCtrl="showCtrl"
      :shouldLocation="shouldLocation"
      :containerInfo="containerInfo"
      :searchInputInfo="searchInputInfo"
      :locationInfo="locationInfo"
      :geoSuccessFn="geoSuccessFn"
      :geoFailFn="geoFailFn"
      :poiSelectFn="poiSelectFn"
      :geoCoderCompleteFn="geoCoderCompleteFn"
      :disabled="disabled"
    />
  </div>
</template>

<script lang="ts">

import {
  ref,
  watch,
  computed,
  nextTick,
  getCurrentInstance,
  defineComponent,
  onMounted,
  onBeforeUnmount,
} from 'vue'
import AMap from './a-map.vue'
import config from './config'

const { mapStyle } = config

export default defineComponent({
  name: 'IfAmap',
  components: {
    AMap
  },
  props: {
    getLocationInfo: {
      type: Function,
      default: () => () => {}
    },
    mapStyle: {
      type: Object,
      default: () => {}
    },
    containerInfo: {
      type: Object,
      default: () => {}
    },
    searchInputInfo: {
      type: Object,
      default: () => {}
    },
    // 地图类型：定位
    shouldLocation: {
      type: Boolean,
      default: false
    },
    value: {
      type: Object,
      default: () => {}
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  setup(props) {
    // 一、变量的处理
    const locationInfo = ref<any>(props.value || {})
    const showCtrl = ref(false)
    const internalInstance:any = getCurrentInstance()

    // 二、函数的处理
    const updateMap = async (info:any) => {
      locationInfo.value = info
      await nextTick() // 让location进行一次数据同步
      internalInstance.ctx.$refs.amap.updateMap() // 调用更新
    }
    // 定位成功
    const geoSuccessFn = async (data:any) => {
      locationInfo.value = data
      props.getLocationInfo(locationInfo.value)
    }
    // 定位失败
    const geoFailFn = () => {
      locationInfo.value = {}
      props.getLocationInfo(locationInfo.value)
    }
    // poi选择回调
    const poiSelectFn = (data:any) => {
      locationInfo.value = data
      props.getLocationInfo(locationInfo.value)
    }
    // 逆地理编码完成
    const geoCoderCompleteFn = (data:any) => {
      locationInfo.value = data
      props.getLocationInfo(locationInfo.value)
    }
    // 地址名称修改
    const locationNameChange = (text:string) => {
      locationInfo.value.name = text
      props.getLocationInfo(locationInfo.value)
    }
    // 地图点击监听
    const documentClickListener = (e:any) => {
      // 判断当前是否是input框, 则显示地图
      const isCurrentInput = e.srcElement?.offsetParent?.firstChild?.className === 'if-location'
      if (isCurrentInput) {
        showCtrl.value = true
        return
      }
      try {
        // 其他判断, 点击地图上，则地图显示，点击地图外，则地图隐藏
        const currrentClassNameList = e.srcElement?.className?.split(' ')
        const parentClassNameList = !e.srcElement?.offsetParent ? [] : e.srcElement?.offsetParent?.className.split(' ')
        const cnList = currrentClassNameList.concat(parentClassNameList)
        const list = ['amap', 'if-location', 'auto-item']
        let flag = false
        cnList.some((item:any) => {
          list.some((one) => {
            flag = item.includes(one)
            return flag
          })
          return flag
        })
        // 如果匹配, 则不关闭，否则关闭
        showCtrl.value = flag
      } catch (e) {
        console.log('e', e)
      }
    }

    // 三、计算属性
    const mapWarpStyle = computed(() => ({ ...mapStyle, ...props.mapStyle }))
    const currentLayerClass = computed(() => (showCtrl.value ? '' : 'hide'))

    // 四、对当前监听
    watch(() => props.value, (newVal, oldVal) => {
      const notSame = JSON.stringify(newVal) !== JSON.stringify(oldVal)
      if (notSame) {
        updateMap(newVal)
      }
    })

    // 五、生命周期
    onMounted(() => {
      document.addEventListener('click', documentClickListener, false)
    })
    onBeforeUnmount(() => {
      document.removeEventListener('click', documentClickListener, false)
    })
    return {
      // 1. 变量
      locationInfo,
      showCtrl,
      // 2. 计算属性
      mapWarpStyle,
      currentLayerClass,
      // 3. 方法
      geoSuccessFn,
      geoFailFn,
      poiSelectFn,
      geoCoderCompleteFn,
      locationNameChange,
      documentClickListener,
    }
  },
  methods: {
    // 对外提供定位功能
    doGeoLocation() {
      const refs:any = this.$refs
      refs.amap.doGeoLocation()
    },
    // 对外提供回显功能
    doDesignativeLocation() {
      const refs:any = this.$refs
      refs.amap.doDesignativeLocation()
    }
  }
})
</script>

<style lang="less" scoped>
  .if-amap {
    position: relative;
  }
  .amap-address-text {
    width: 100%;
    height: 32px;
  }
</style>
